package com.distribution.system.manager.channel.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.distribution.common.exception.ServiceException;
import com.distribution.common.utils.StringUtils;
import com.distribution.system.domain.bo.*;
import com.distribution.system.domain.dto.ChoosePhoneDTO;
import com.distribution.system.domain.dto.SendCodeDTO;
import com.distribution.system.domain.entity.AddressChannel;
import com.distribution.system.domain.entity.CmccDaOrder;
import com.distribution.system.domain.entity.CmccDaProduct;
import com.distribution.system.domain.entity.CmccDaUpChannelInfo;
import com.distribution.system.domain.req.ReqResult;
import com.distribution.system.manager.channel.AbstractChannel;
import com.distribution.system.manager.channel.channelInfo.enums.DefaultChannelEnum;
import com.distribution.system.service.AddressChannelService;
import com.distribution.system.utils.MD5Util;
import com.distribution.system.utils.http.HttpRequestUtils;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.distribution.system.utils.DictionarySortUtil.dictSort;

/**
 * @author Liping Huo
 * @date 2023/5/23 1:05
 */
@Slf4j
public class DefaultChannel extends AbstractChannel {
    private static final Logger lhtOrderSearchLog = LoggerFactory.getLogger("lhtOrderSearchLog");

    private static final String KEYWORDS = "";

    public DefaultChannel(CmccDaUpChannelInfoBO cmccDaUpChannelInfoBO) {
        super(cmccDaUpChannelInfoBO);
    }

    @Override
    public AddressInfoBo getChannelAddressInfo(AddressNameBo addressNameBo, AddressChannelService addressChannelService) {
        return null;
    }

    @Override
    public String configPlaceOrderRequestParams(CmccDaOrder cmccDaOrder, CmccDaProduct cmccDaProduct, AddressInfoBo addressInfoBo) {
        log.info("配置老后台下单接口参数...");
        AddressChannel addressInfo = addressInfoBo.getAddressInfo();
        AddressChannel attributeInfo = addressInfoBo.getAttributeInfo();
        // 生成订单号
        orderId = "LHT" + DateUtil.format(DateUtil.date(), "yyyyMMdd") + IdUtil.getSnowflake(1, 1).nextIdStr().substring(8,18);
        HashMap<String, Object> map = new HashMap<>(1 << 4);
        //配置请求参数
        map.put("postProvinceCode", addressInfo.getProvinceCode());
        map.put("postCityCode", addressInfo.getCityCode());
        map.put("postDistrictCode", addressInfo.getDistrictCode());
        map.put("postAddress", addressInfo.getProvinceName() + addressInfo.getCityName() + addressInfo.getDistrictName() + cmccDaOrder.getAddressStreet());
        map.put("postMobile", cmccDaOrder.getCustomerPhone());
        map.put("name", cmccDaOrder.getCustomerName());
        map.put("card", cmccDaOrder.getCustomerCertNo());
        map.put("provinceCode", attributeInfo.getEssProvinceCode());
        map.put("cityCode", attributeInfo.getEssCityCode());
        if ("1".equals(cmccDaProduct.getSelectNumberFlag())) {
            map.put("phone", cmccDaOrder.getChoosePhone());
//            map.put("uuid", cmccDaOrder.getPhoneUuid());
        } else {
            map.put("phone", "666666");
        }
        map.put("goodsCode", cmccDaOrder.getProductParam());
        if (!"1".equals(cmccDaProduct.getBroadbandFlag()) && "1".equals(cmccDaProduct.getCodeFlag())) {
            map.put("code", cmccDaOrder.getCode());
        }
//        map.put("keywords", KEYWORDS);
        map.put("appId", interfaceParamsMap.get(DefaultChannelEnum.APP_ID.getName()));
        String sign = getSign(map, interfaceParamsMap.get(DefaultChannelEnum.APP_KEY.getName()));
        map.put("sign", sign);
        return new JSONObject(map).toString();
    }

    @Override
    public String sendPlaceOrderRequest(String requestJsonStr) {
        return HttpRequestUtils.sendPost(interfaceUrlsMap.get(DefaultChannelEnum.PLACE_ORDER.getName()), requestJsonStr);
    }

    @Override
    public ReqResult parsePlaceOrderResponseStr(JSONObject responseJsonObject) {
        //响应
        String msg = responseJsonObject.getString("msg");
        if (responseJsonObject.getInteger("code") != 200) {// 失败
            return ReqResult.error(msg);
        } else {
            JSONObject data = responseJsonObject.getJSONObject("data");
            UnOrderResultBo unOrderResultBo = new UnOrderResultBo();
            unOrderResultBo.setOrderId(orderId);
            unOrderResultBo.setChannelOrderNo(data.getString("orderNo"));
            return ReqResult.success(msg, unOrderResultBo);
        }
    }

    @Override
    public String configChoosePhoneRequestParams(ChoosePhoneDTO choosePhoneDTO, CmccDaProduct cmccDaProduct, AddressInfoBo addressInfoBo) {
        HashMap<String, Object> map = new HashMap<>(1 << 2);
        map.put("appId", interfaceParamsMap.get(DefaultChannelEnum.APP_ID.getName()));
        map.put("keywords", StringUtils.isBlank(choosePhoneDTO.getKeywords()) ? "" : choosePhoneDTO.getKeywords());
        map.put("cityCode", addressInfoBo.getAttributeInfo().getEssCityCode());
        map.put("provinceCode", addressInfoBo.getAttributeInfo().getEssProvinceCode());
        map.put("page", choosePhoneDTO.getPage());
        map.put("goodsCode", cmccDaProduct.getProductParam());
        //map.put("name", choosePhoneDTO.getName());
        //map.put("card", choosePhoneDTO.getCard());
        String sign = getSign(map, interfaceParamsMap.get(DefaultChannelEnum.APP_KEY.getName()));
        //System.out.println("apiKey:" + channelParamsMap.get(DefaultChannelEnum.NUMERICAL.getCode()).getTripartiteApiAppKey());
        map.put("sign", sign);
        return new JSONObject(map).toString();
    }

    @Override
    public String sendChoosePhoneRequest(String requestJsonStr) {
        return HttpRequestUtils.sendPost(interfaceUrlsMap.get(DefaultChannelEnum.CHOOSE_PHONE.getName()), requestJsonStr);
    }

    @Override
    public ReqResult parseChoosePhoneResponseStr(JSONObject responseJsonObject) {
        String msg = responseJsonObject.getString("msg");
        if (responseJsonObject.getInteger("code") != 200) {
            return ReqResult.error(msg);
        } else {
            ChoosePhoneResultBO choosePhoneResultBO = new ChoosePhoneResultBO();
            List<String> numArray = new ArrayList<>();
            for (Object object : responseJsonObject.getJSONArray("list")) {
                Long phoneNum = (Long) object;
                if (!StringUtils.isEmpty(phoneNum.toString())) {
                    numArray.add(phoneNum.toString());
                }
            }
            choosePhoneResultBO.setNumArray(numArray);
            String uniqsn = responseJsonObject.getString("uuid");
            if (!StringUtils.isEmpty(uniqsn)){
                choosePhoneResultBO.setUuid(uniqsn);
            }
            return ReqResult.success(choosePhoneResultBO);
        }
    }

    @Override
    public ReqResult sendCardSmsCode(CmccDaProduct cmccDaProduct, SendCodeDTO sendCodeDTO) {
        HashMap<String, Object> map = new HashMap<>(1 << 2);
        map.put("card",sendCodeDTO.getCertNum());
        map.put("name",sendCodeDTO.getCertName());
        map.put("postMobile",sendCodeDTO.getCustomerPhone());
        map.put("goodsCode", cmccDaProduct.getProductParam());
        map.put("appId", interfaceParamsMap.get(DefaultChannelEnum.APP_ID.getName()));
        map.put("keywords", KEYWORDS);
        String sign = getSign(map, interfaceParamsMap.get(DefaultChannelEnum.APP_KEY.getName()));
        map.put("sign", sign);
        String requestJson = new JSONObject(map).toString();
        JSONObject responseJson = JSONObject.parseObject(HttpRequestUtils.sendPost(interfaceUrlsMap.get(DefaultChannelEnum.SEND_SMS.getName()), requestJson));
        Integer code = responseJson.getInteger("code");
        String msg = responseJson.getString("msg");
        return code == 200 ? ReqResult.success(msg) : ReqResult.error(msg);
    }


    @Override
    public RefreshOrderBO getRefreshOrderBO(CmccDaOrder cmccDaOrder) {
        // 老后台是根据渠道方订单编号更新的
        List<CmccDaOrder> orderList = new ArrayList<>();
        orderList.add(cmccDaOrder);
        Map<CmccDaOrder,RefreshOrderBO> refreshOrderBOMap = getRefreshOrderBOList(orderList);
        return refreshOrderBOMap.isEmpty() ? null : refreshOrderBOMap.get(cmccDaOrder);
    }

    @Override
    public Map<CmccDaOrder,RefreshOrderBO> getRefreshOrderBOMap(List<CmccDaOrder> orderList) {
        return getRefreshOrderBOList(orderList);
    }
    private Map<CmccDaOrder,RefreshOrderBO> getRefreshOrderBOList(List<CmccDaOrder> orderList){
        List<CmccDaOrder> subList = orderList.subList(0, Math.min(100, orderList.size()));
        String channelOrderNos = subList.stream().map(CmccDaOrder::getChannelOrderNo).collect(Collectors.joining(","));
        HashMap<String, Object> map = new HashMap<>(1 << 2);
        map.put("appId", interfaceParamsMap.get(DefaultChannelEnum.APP_ID.getName()));
        map.put("orderNos", channelOrderNos);
        String sign = getSign(map, interfaceParamsMap.get(DefaultChannelEnum.APP_KEY.getName()));
        map.put("sign", sign);
        String requestJson = new JSONObject(map).toString();
        log.info("【老后台】查单请求 => {}",requestJson);
        lhtOrderSearchLog.info("【老后台】查单请求 => {}",requestJson);
        JSONObject responseJson = JSONObject.parseObject(HttpRequestUtils.sendPost(interfaceUrlsMap.get(DefaultChannelEnum.SELECT_ORDER.getName()), requestJson));
        log.info("【老后台】查单响应 => {}",responseJson.toString());
        lhtOrderSearchLog.info("【老后台】查单响应 => {}",responseJson.toString());
        Map<CmccDaOrder,RefreshOrderBO> refreshOrderBOMap = new HashMap<>();
        if (responseJson.getInteger("code") != 200) {// 失败
            throw new ServiceException(responseJson.getString("msg"));
        }
        // 成功
        JSONArray jsonArray = responseJson.getJSONArray("data");
        if (!jsonArray.isEmpty()) {
            for (Object object : jsonArray) {
                JSONObject jsonObject = (JSONObject) object;
                RefreshOrderBO refreshOrderBO = new RefreshOrderBO();
                refreshOrderBO.setChannelOrderNo(jsonObject.getString("sn"));// 渠道方订单号
                refreshOrderBO.setStatus(jsonObject.getString("status"));// 状态:2=进行中,3=已成功,-1=失败
                refreshOrderBO.setPhone(jsonObject.getString("phone"));// 选号手机号
                refreshOrderBO.setProductStatus(jsonObject.getString("u_status"));// 卡状态
                refreshOrderBO.setStatusMsg(jsonObject.getString("status_msg"));// 失败原因
                refreshOrderBO.setScMoney(jsonObject.getString("sc_money"));// 下单金额（分）
                refreshOrderBO.setCreateTime(jsonObject.getString("createtime")); // 订单处理时间
                // 激活时间或首充时间（根据状态判断是激活或者首充）
                String limitTime = jsonObject.getString("limit_time");
                if (!"0".equals(limitTime)) {
                    long time = Long.parseLong(limitTime);
                    refreshOrderBO.setLimitTime(DateUtil.date(time * 1000L).toString());
                }
                CmccDaOrder cmccDaOrder = orderList.stream().filter(f -> StringUtils.equals(f.getChannelOrderNo(), refreshOrderBO.getChannelOrderNo())).collect(Collectors.toList()).get(0);
                refreshOrderBOMap.put(cmccDaOrder, refreshOrderBO);
            }
        }
        return refreshOrderBOMap;
    }

    /**
     * 获取签名信息
     *
     * @param map json map
     * @return 加密签名
     */
    private static String getSign(Map<String, Object> map, String appKey) {
        List<String> strings = dictSort(map.keySet().toArray(new String[0]));
        StringBuilder stringBuffer = new StringBuilder();
        int size = strings.size();
        for (int i = 0; i < size; i++) {
            stringBuffer.append(strings.get(i)).append("=").append(map.get(strings.get(i)));
            if (i != size - 1) {
                stringBuffer.append("&");
            }
        }
        stringBuffer.append("&appKey=").append(appKey);
        //System.out.println("拼接参数：" + stringBuffer.toString());
        return MD5Util.stringToMD5((stringBuffer.toString()));
    }

    @Override
    public void refreshChannelCommission(CmccDaUpChannelInfo cmccDaUpChannelInfo) {
    }
}
